package com.iwomy.secureplat.platform.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.iwomy.secureplat.common.core.exception.PlatformBizErrorCodes;
import com.iwomy.secureplat.common.core.util.MsgUtils;
import com.iwomy.secureplat.common.core.util.R;
import com.iwomy.secureplat.common.data.tenant.TenantContextHolder;
import com.iwomy.secureplat.common.excel.annotation.RequestExcel;
import com.iwomy.secureplat.common.excel.vo.ErrorMessage;
import com.iwomy.secureplat.common.log.annotation.ReckonTime;
import com.iwomy.secureplat.common.log.annotation.SysLog;
import com.iwomy.secureplat.common.security.util.SecurityUtils;
import com.iwomy.secureplat.platform.constant.RedisConstants;
import com.iwomy.secureplat.platform.dto.BasicDeviceDTO;
import com.iwomy.secureplat.platform.entity.BasicDeviceEntity;
import com.iwomy.secureplat.platform.entity.BasicExpensesDeptDetailEntity;
import com.iwomy.secureplat.platform.entity.BasicExpensesDviceConfigEntity;
import com.iwomy.secureplat.platform.exception.PlatformException;
import com.iwomy.secureplat.platform.service.*;

import com.iwomy.secureplat.platform.transmission.entity.SensorTransmissionData;
import com.iwomy.secureplat.platform.utils.RedisClient;
import com.iwomy.secureplat.platform.utils.RemoteDeptUtils;
import com.iwomy.secureplat.platform.vo.*;
import org.springframework.security.access.prepost.PreAuthorize;
import com.iwomy.secureplat.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 设备信息表
 *
 * @author pig
 * @date 2023-11-21 15:14:16
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/basicDevice")
@Tag(description = "basicDevice", name = "设备信息表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class BasicDeviceController {

	private final BasicDeviceService basicDeviceService;

	private final BasicInstallLocationService basicInstallLocationService;

	private final BasicExpensesDeptDetailService expensesDeptDetailService;

	private final RemoteDeptUtils remoteDeptUtils;

	private final RealTimeDataService realTimeDataService;

	private final BasicExpensesDviceConfigService expensesDviceConfigService;

	private final AlarmDeviceRulesService alarmDeviceRulesService;

	private final RedisClient redisClient;

	/**
	 * 分页查询
	 *
	 * @param page           分页对象
	 * @param basicDeviceDTO 设备信息表
	 * @return
	 */
	@Operation(summary = "分页查询", description = "分页查询")
	@GetMapping("/page")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_view')")
	@ReckonTime
	public R getBasicDevicePage(@ParameterObject Page page, @ParameterObject BasicDeviceDTO basicDeviceDTO) {
		Page<BasicDeviceVO> basicDevicePage = basicDeviceService.getBasicDevicePage(page, basicDeviceDTO);
		List<BasicDeviceVO> records = basicDevicePage.getRecords();
		for (BasicDeviceVO record : records) {
			Long installLocationId = record.getInstallLocationId();
			if (installLocationId != null && !installLocationId.equals(0L)) {
				BasicInstallLocationVO basicInstallLocation = basicInstallLocationService.getInstallLocation(installLocationId);
				if (ObjectUtil.isNotEmpty(basicInstallLocation)) {
					record.setInstallAddress(basicInstallLocation.getAddress());
					record.setInstallWorker(basicInstallLocation.getInstallWorker());
					record.setInstallWorkerPhone(basicInstallLocation.getInstallWorkerPhone());
					record.setDetailAddress(basicInstallLocation.getDetailAddress());
					record.setLongitude(basicInstallLocation.getLongitude());
					record.setLatitude(basicInstallLocation.getLatitude());
					record.setBasicInstallLocation(basicInstallLocation);
				}
				SensorTransmissionData sensorTransmissionData = realTimeDataService.getRedisByImei(record.getImei());
				record.setSensorTransmissionData(sensorTransmissionData);
			}
		}
		return R.ok(basicDevicePage);
	}

	/**
	 * 分页查询
	 *
	 * @param basicDevice 设备列表
	 * @return
	 */
	@Operation(summary = "分页查询", description = "分页查询")
	@GetMapping("/list")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_view')")
	public R getBasicDeviceList(@ParameterObject BasicDeviceDTO basicDevice) {
		return R.ok(basicDeviceService.listByScope(basicDevice));
	}

	/**
	 * 通过id查询设备信息表
	 *
	 * @param id id
	 * @return R
	 */
	@Operation(summary = "通过id查询", description = "通过id查询")
	@GetMapping("/{id}")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_view')")
	public R getById(@PathVariable("id") Long id) {
		BasicDeviceVO basicDevice = basicDeviceService.getByIds(id);
		if (basicDevice.getInstallLocationId() != null && !basicDevice.getInstallLocationId().equals(0L)) {
			BasicInstallLocationVO wrapperInstallLocation = new BasicInstallLocationVO();
			wrapperInstallLocation.setId(basicDevice.getInstallLocationId());
			BasicInstallLocationVO basicInstallLocationVO = basicInstallLocationService.getByIds(wrapperInstallLocation.getId());
			basicDevice.setBasicInstallLocation(basicInstallLocationVO);
		}
		return R.ok(basicDevice);
	}

	/**
	 * 新增设备信息表
	 *
	 * @param basicDevice 设备信息表
	 * @return R
	 */
	@Operation(summary = "新增设备信息表", description = "新增设备信息表")
	@SysLog("新增设备信息表")
	@PostMapping
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_add')")
	public R save(@RequestBody BasicDeviceDTO basicDevice) {
		if (basicDevice.getImeis().isEmpty()) {
			throw new PlatformException("输入的IMEI号格式有误，不允许新增");
		}
		Set<String> uniqueImeis = new HashSet<>(basicDevice.getImeis());
		if (uniqueImeis.size() != basicDevice.getImeis().size()) {
			throw new PlatformException("输入的IMEI号重复，不允许新增");
		}
		basicDevice.setDeptId(SecurityUtils.getUser().getDeptId());
		basicDevice.setCreateDeptId(SecurityUtils.getUser().getDeptId());
		List<BasicDeviceEntity> deviceEntities = new ArrayList<>();
		for (String imei : basicDevice.getImeis()) {
			BasicDeviceEntity basicDeviceEntity = new BasicDeviceEntity();
			BeanUtil.copyProperties(basicDevice, basicDeviceEntity);
			basicDeviceEntity.setImei(imei);
			basicDeviceEntity.setType(10);
			deviceEntities.add(basicDeviceEntity);
		}

		Map<String, Object> data = remoteDeptUtils.getDept(SecurityUtils.getUser().getDeptId());
		String parentIdString = (String) data.getOrDefault("parentId", null);
		Long parentId = Long.parseLong(parentIdString);

		//不是租户时才判断余额足不足
		if (parentId != 0) {
			QuerySmsTtsCountVO querySmsTts = expensesDeptDetailService.queryDeptCount(SecurityUtils.getUser().getDeptId());
			if (querySmsTts.getDeviceRemainNum() < basicDevice.getImeis().size()) {
//				throw new PlatformException("设备可用数量已达上限，请联系管理员");
				throw new PlatformException(MsgUtils.getMessage(PlatformBizErrorCodes.DEVICE_AVAILABLE_NUMBER_LIMIT));
			}
		}
		Long tenantId = TenantContextHolder.getTenantId();

		LambdaQueryWrapper<BasicDeviceEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.in(BasicDeviceEntity::getImei, basicDevice.getImeis());
		TenantContextHolder.clear();
		List<BasicDeviceEntity> one = basicDeviceService.getBaseMapper().selectList(wrapper);
		TenantContextHolder.setTenantId(tenantId);
		if (one != null && !one.isEmpty()) {
//			throw new PlatformException("IMEI号已存在");
			throw new PlatformException(MsgUtils.getMessage(PlatformBizErrorCodes.DEVICE_IMEI_EXIST));
		}

		//新增一台设备扣除一台设备
		basicDeviceService.saveBatch(deviceEntities);
		alarmDeviceRulesService.addDeviceRulesByDevice(deviceEntities, basicDevice.getRulesIds());
		if (parentId != 0) {
			expensesDeptDetailService.deductDevice(basicDevice.getImeis().size(), SecurityUtils.getUser().getDeptId());
		}
		return R.ok();
	}

	/**
	 * 修改设备信息表
	 *
	 * @param basicDeviceDTO 设备信息表
	 * @return R
	 */
	@Operation(summary = "修改设备信息表", description = "修改设备信息表")
	@SysLog("修改设备信息表")
	@PutMapping
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_edit')")
	public R updateById(@RequestBody BasicDeviceDTO basicDeviceDTO) {

		BasicDeviceEntity basicDevice = BeanUtil.copyProperties(basicDeviceDTO, BasicDeviceEntity.class);
		List deviceList = new ArrayList();
		deviceList.add(basicDevice);
//		alarmDeviceRulesService.addDeviceRulesByDevice(deviceList,basicDeviceDTO.getRulesIds());
		return R.ok(basicDeviceService.updateById(basicDevice));
	}

	/**
	 * 修改设备告警规则
	 *
	 * @param basicDeviceDTO 修改设备告警规则
	 * @return R
	 */
	@Operation(summary = "修改设备告警规则", description = "修改设备告警规则")
	@SysLog("修改设备信息表")
	@PutMapping("updateRuleByImei")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_edit')")
	public R updateRuleByImei(@RequestBody BasicDeviceDTO basicDeviceDTO) {
		BasicDeviceEntity byImei = basicDeviceService.getByImei(basicDeviceDTO.getImei());
		List deviceList = new ArrayList();
		deviceList.add(byImei);
		alarmDeviceRulesService.addDeviceRulesByDevice(deviceList, basicDeviceDTO.getRulesIds());
		return R.ok();
	}

	/**
	 * 启用禁用
	 *
	 * @param basicDevice 设备信息
	 * @return R
	 */
	@Operation(summary = "启用禁用设备", description = "启用禁用设备")
	@SysLog(expression = "'启用禁用设备'.concat(#basicDevice.remarks)")
	@PutMapping("/enableOrDisable")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_enableOrDisable')")
	public R enableOrDisable(@RequestBody BasicDeviceEntity basicDevice) {
		basicDeviceService.deactivateDevice(basicDevice);
		return R.ok();
	}

	/**
	 * 通过id删除设备信息表
	 *
	 * @param basicDeviceEntity id列表
	 * @return R
	 */
	@Operation(summary = "通过id删除设备信息表", description = "通过id删除设备信息表")
	@SysLog("通过id删除设备信息表")
	@DeleteMapping
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_del')")
	public R removeById(@RequestBody List<BasicDeviceEntity> basicDeviceEntity) {
		boolean hasNonNullInstallLocationId = basicDeviceEntity.stream()
				.anyMatch(entity -> entity.getInstallLocationId() != null && entity.getInstallLocationId() != 0);
		if (hasNonNullInstallLocationId) {
//			throw new PlatformException("已绑定设备无法删除，请先解除绑定");
			throw new PlatformException(MsgUtils.getMessage(PlatformBizErrorCodes.DEVICE_ID_USED_DELETE));
		}
		List<BasicExpensesDeptDetailEntity> expensesDeptDetailList = new ArrayList<>();
		for (BasicDeviceEntity device : basicDeviceEntity) {

			LambdaQueryWrapper<BasicExpensesDviceConfigEntity> wrapper = new LambdaQueryWrapper<>();
			wrapper.in(BasicExpensesDviceConfigEntity::getDeviceId, device.getId());

			List<BasicExpensesDviceConfigEntity> expensesDeviceDetail = expensesDviceConfigService.list(wrapper);

			if (ObjectUtil.isNotEmpty(expensesDeviceDetail)) {
				Long giveDeptId = expensesDeviceDetail.get(0).getGiveDeptId();
				Map<String, Object> data = remoteDeptUtils.getDept(giveDeptId);
				String parentIdString = (String) data.getOrDefault("parentId", null);
				Long parentId = Long.parseLong(parentIdString);

				if (!parentId.equals(0L)) {
					BasicExpensesDviceConfigVO expensesDviceConfigVO = expensesDviceConfigService.selectDeviceRemain(expensesDeviceDetail);
					//出库单位的deptId
					QuerySmsTtsCountVO querySmsTtsCountVO = expensesDeptDetailService.queryDeptCount(giveDeptId);

					BasicExpensesDeptDetailEntity expensesDeptDetail = new BasicExpensesDeptDetailEntity();
					expensesDeptDetail.setSmsRemainNum(querySmsTtsCountVO.getSmsRemainNum() + expensesDviceConfigVO.getSmsRemainNum());
					expensesDeptDetail.setSmsAddNumRemain(expensesDviceConfigVO.getSmsRemainNum());
					expensesDeptDetail.setTtsRemainNum(querySmsTtsCountVO.getTtsRemainNum() + expensesDviceConfigVO.getTtsRemainNum());
					expensesDeptDetail.setTtsAddNumRemain(expensesDviceConfigVO.getTtsRemainNum());
					expensesDeptDetail.setDeviceAddNumRemain(0);
					expensesDeptDetail.setDeviceRemainNum(querySmsTtsCountVO.getDeviceRemainNum());
					expensesDeptDetail.setSmsAddNum(expensesDviceConfigVO.getSmsRemainNum());
					expensesDeptDetail.setTtsAddNum(expensesDviceConfigVO.getTtsRemainNum());
					expensesDeptDetail.setDeviceAddNum(0);
					expensesDeptDetail.setDeptId(device.getDeptId());
					expensesDeptDetail.setDeliveryMethod(10);
					expensesDeptDetail.setAddPlatformFeeYears(0);
					expensesDeptDetail.setPlatformFeeYears(querySmsTtsCountVO.getPlatformFeeYears());
					expensesDeptDetail.setPlatformExpireDate(querySmsTtsCountVO.getPlatformExpireDate());
					expensesDeptDetailList.add(expensesDeptDetail);
				}
			}

			redisClient.del(RedisConstants.REDIS_KEY_DEVICE_ONLINE + device.getImei());
		}

		if (ObjectUtil.isNotEmpty(expensesDeptDetailList)) {
			expensesDeptDetailService.saveBatch(expensesDeptDetailList);
		}

		Long[] ids = basicDeviceEntity.stream()
				.map(BasicDeviceEntity::getId)
				.toArray(Long[]::new);
		return R.ok(basicDeviceService.removeByIds(Arrays.asList(ids)));
	}


	/**
	 * 导出excel 表格
	 *
	 * @param basicDevice 查询条件
	 * @param ids         导出指定ID
	 * @return excel 文件流
	 */
	@ResponseExcel
	@GetMapping("/export")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_export')")
	public List<BasicDeviceEntity> export(BasicDeviceEntity basicDevice, Long[] ids) {
		return basicDeviceService.list(Wrappers.lambdaQuery(basicDevice).in(ArrayUtil.isNotEmpty(ids), BasicDeviceEntity::getId, ids));
	}

	/**
	 * 导入imei号
	 *
	 * @param excelVOList   imei列表
	 * @param bindingResult 错误信息列表
	 * @return R
	 */
	@PostMapping("/import")
	public R importDevice(@RequestExcel List<BasicDeviceExcelVO> excelVOList, BindingResult bindingResult) {
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
		Map<String, Object> data = remoteDeptUtils.getDept(SecurityUtils.getUser().getDeptId());
		String parentIdString = (String) data.getOrDefault("parentId", null);
		Long parentId = Long.parseLong(parentIdString);
		R result = null;
		//不是租户时才判断余额足不足
		if (!parentId.equals(0L)) {
			QuerySmsTtsCountVO querySmsTts = expensesDeptDetailService.queryDeptCount(SecurityUtils.getUser().getDeptId());
			if (querySmsTts.getDeviceRemainNum() < excelVOList.size()) {
				Set<String> errorMsg = new HashSet<>();
				errorMsg.add("设备可用数量已达上限，请联系管理员");
				errorMessageList.add(new ErrorMessage(1L, errorMsg));
				return R.failed(errorMessageList);
			} else {
				result = basicDeviceService.importDevice(excelVOList, bindingResult, parentId);

				if (result.getCode() == 0 && !parentId.equals(0L)) {
					expensesDeptDetailService.deductDevice(excelVOList.size(), SecurityUtils.getUser().getDeptId());
				}
			}
		} else {
			result = basicDeviceService.importDevice(excelVOList, bindingResult, parentId);
		}
		return result;
	}


	@Operation(summary = "大屏故障原因获取型号列表", description = "大屏故障原因获取型号列表")
	@GetMapping("/homeGetModelListByDevice")
	public R homeGetModelListByDevice() {
		return R.ok(basicDeviceService.homeGetModelListByDevice());
	}

	/**
	 * 设备总览设备列表
	 *
	 * @return R
	 */
	@ReckonTime
	@Operation(summary = "设备总览设备列表", description = "设备总览设备列表")
	@GetMapping("/deviceList")
	public R getdeviceList(@ParameterObject BasicDeviceDTO basicDeviceDTO) {
		List<BasicDeviceVO> basicDevice = basicDeviceService.getdeviceList(basicDeviceDTO);
		for (BasicDeviceVO record : basicDevice) {
			SensorTransmissionData sensorTransmissionData = realTimeDataService.getRedisByImei(record.getImei());
			record.setSensorTransmissionData(sensorTransmissionData);
		}
		return R.ok(basicDevice);
	}

	/**
	 * 所有设备型号
	 *
	 * @return R
	 */
	@Operation(summary = "设备总览设备列表", description = "设备总览设备列表")
	@GetMapping("/allModel")
	public R allModel() {


		return R.ok(basicDeviceService.allModel());

	}

	/**
	 * 新增设备信息表
	 *
	 * @param basicDevice 设备信息表
	 * @return R
	 */
	@Operation(summary = "新增设备信息表", description = "新增设备信息表")
	@SysLog("新增设备信息表")
	@PostMapping("/videoAdd")
	@PreAuthorize("@pms.hasPermission('platform_basicDevice_add')")
	public R videoAdd(@RequestBody BasicDeviceEntity basicDevice) {
		Long parentId = remoteDeptUtils.getParentId(SecurityUtils.getUser().getDeptId());

		//不是租户时才判断余额足不足
		if (!parentId.equals(0L)) {
			QuerySmsTtsCountVO querySmsTts = expensesDeptDetailService.queryDeptCount(SecurityUtils.getUser().getDeptId());
			if (querySmsTts.getDeviceRemainNum() <= 0) {
				throw new PlatformException(MsgUtils.getMessage(PlatformBizErrorCodes.DEVICE_AVAILABLE_NUMBER_LIMIT));
			}
		}
		Long tenantId = TenantContextHolder.getTenantId();
		BasicDeviceEntity wrapperEntity = new BasicDeviceEntity();
		wrapperEntity.setImei(basicDevice.getImei());
		LambdaQueryWrapper<BasicDeviceEntity> wrapper = Wrappers.lambdaQuery(wrapperEntity);
		TenantContextHolder.clear();
		BasicDeviceEntity one = basicDeviceService.getOne(wrapper);
		TenantContextHolder.setTenantId(tenantId);
		if (ObjectUtil.isNotNull(one) && !one.getId().equals(basicDevice.getId())) {
			throw new PlatformException(MsgUtils.getMessage(PlatformBizErrorCodes.DEVICE_IMEI_EXIST));
		}
		basicDevice.setDeptId(SecurityUtils.getUser().getDeptId());
		basicDevice.setType(20);
		//新增一台设备扣除一台设备
		basicDeviceService.save(basicDevice);
		if (!parentId.equals(0L)) {
			expensesDeptDetailService.deductDevice(1, SecurityUtils.getUser().getDeptId());
		}
		return R.ok();
	}


}
